#pragma once

#include "base_view_model.h"
#include "kernel/dtos/map_display_dto.h"
#include "kernel/domain/map_types.h"
#include <QPointF>
#include <QString>
#include <QVector>
#include <QColor>
#include <QRectF>
#include <QVariantList>

// Forward declaration to avoid including application layer headers
namespace application {
class MapApplicationService;
}

namespace presentation {

class MapViewModel : public BaseViewModel {
    Q_OBJECT

    // Map information properties
    Q_PROPERTY(QString mapName READ mapName NOTIFY mapChanged)
    Q_PROPERTY(QRectF mapBounds READ mapBounds NOTIFY mapChanged)
    Q_PROPERTY(double mapResolution READ mapResolution NOTIFY mapChanged)
    Q_PROPERTY(bool isMapLoaded READ isMapLoaded NOTIFY mapLoadedChanged)

    // Multi-floor properties
    Q_PROPERTY(int currentFloor READ currentFloor NOTIFY currentFloorChanged)
    Q_PROPERTY(QVariantList loadedFloors READ loadedFloors NOTIFY loadedFloorsChanged)

    // Current position tracking
    Q_PROPERTY(QPointF currentPosition READ currentPosition NOTIFY currentPositionChanged)
    Q_PROPERTY(double currentAngle READ currentAngle NOTIFY currentPositionChanged)

    // Map display data for the background renderer
    Q_PROPERTY(kernel::MapDisplayDto mapDisplayData READ mapDisplayData NOTIFY mapChanged)

public:
    // Default constructor for QML
    explicit MapViewModel(QObject* parent = nullptr);
    // Constructor with service injection
    explicit MapViewModel(application::MapApplicationService* mapAppService, QObject* parent = nullptr);
    ~MapViewModel() override = default;

    // Override BaseViewModel methods
    void initialize() override;
    void cleanup() override;

    // Property getters
    QString mapName() const { return mapName_; }
    QRectF mapBounds() const { return mapBounds_; }
    double mapResolution() const { return mapResolution_; }
    bool isMapLoaded() const { return isMapLoaded_; }
    int currentFloor() const { return currentFloor_; }
    QVariantList loadedFloors() const {
        QVariantList floors;
        floors.reserve(loadedFloors_.size());
        for (int floor : loadedFloors_) {
            floors.append(floor);
        }
        return floors;
    }
    QPointF currentPosition() const { return currentPosition_; }
    double currentAngle() const { return currentAngle_; }
    kernel::MapDisplayDto mapDisplayData() const { return mapDisplayData_; }

    // Invokable methods for QML
    Q_INVOKABLE bool loadMap(const QString& mapName);
    Q_INVOKABLE bool switchToFloor(int floor);
    Q_INVOKABLE void refreshMapData();
    Q_INVOKABLE QVector<QString> getStationNames() const;
    Q_INVOKABLE QPointF getStationPosition(const QString& stationName) const;
    Q_INVOKABLE int getFloorForMap(const QString& mapName) const;

signals:
    void mapChanged();
    void mapLoadedChanged();
    void currentFloorChanged();
    void loadedFloorsChanged();
    void currentPositionChanged();
    void mapLoadFailed(const QString& error);

private slots:
    void onMapLoadFinished();
    void onMapLoadFailed(const QString& error);
    void onCurrentPositionChanged();

private:
    application::MapApplicationService* mapAppService_;

    // Cached properties
    QString mapName_;
    QRectF mapBounds_;
    double mapResolution_{1.0};
    bool isMapLoaded_{false};
    int currentFloor_{-1};
    QVector<int> loadedFloors_;
    QPointF currentPosition_;
    double currentAngle_{0.0};
    kernel::MapDisplayDto mapDisplayData_;

    void updateCachedProperties();
};

} // namespace presentation
